// 批量操作管理器

import { BaseManager } from '../core/BaseManager';
import { RedisClient } from '../core/RedisClient';
import { KeyGenerator } from '../utils/keyGenerator';

export interface BatchOperation {
  type: 'set' | 'get' | 'del' | 'incr' | 'expire';
  key: string;
  value?: any;
  ttl?: number;
}

export interface BatchResult {
  success: boolean;
  results: any[];
  errors: string[];
  executionTime: number;
}

export class BatchManager extends BaseManager {
  private operations: BatchOperation[] = [];
  private maxBatchSize: number = 1000;

  constructor(client: RedisClient) {
    super(client, new KeyGenerator({ prefix: 'batch' }));
  }

  /**
   * 添加批量操作
   */
  addOperation(operation: BatchOperation): this {
    if (this.operations.length >= this.maxBatchSize) {
      throw new Error(`Batch size cannot exceed ${this.maxBatchSize} operations`);
    }

    this.operations.push(operation);
    return this;
  }

  /**
   * 添加设置操作
   */
  set(key: string, value: any, ttl?: number): this {
    const operation: BatchOperation = { type: 'set', key, value };
    if (ttl !== undefined) {
      operation.ttl = ttl;
    }
    return this.addOperation(operation);
  }

  /**
   * 添加获取操作
   */
  get(key: string): this {
    return this.addOperation({ type: 'get', key });
  }

  /**
   * 添加删除操作
   */
  del(key: string): this {
    return this.addOperation({ type: 'del', key });
  }

  /**
   * 添加增量操作
   */
  incr(key: string, value: number = 1): this {
    return this.addOperation({ type: 'incr', key, value });
  }

  /**
   * 添加过期操作
   */
  expire(key: string, ttl: number): this {
    return this.addOperation({ type: 'expire', key, ttl });
  }

  /**
   * 执行批量操作
   */
  async executeBatch(): Promise<BatchResult> {
    const startTime = this.now();
    const results: any[] = [];
    const errors: string[] = [];

    try {
      if (this.operations.length === 0) {
        return {
          success: true,
          results: [],
          errors: [],
          executionTime: this.now() - startTime,
        };
      }

      // 使用Redis管道执行批量操作
      const pipeline = this.createPipeline();

      for (const operation of this.operations) {
        try {
          switch (operation.type) {
            case 'set':
              if (operation.ttl) {
                pipeline.setex(operation.key, operation.ttl, JSON.stringify(operation.value));
              } else {
                pipeline.set(operation.key, JSON.stringify(operation.value));
              }
              break;
            case 'get':
              pipeline.get(operation.key);
              break;
            case 'del':
              pipeline.del(operation.key);
              break;
            case 'incr':
              if (operation.value && operation.value !== 1) {
                pipeline.incrby(operation.key, operation.value);
              } else {
                pipeline.incr(operation.key);
              }
              break;
            case 'expire':
              pipeline.expire(operation.key, operation.ttl!);
              break;
            default:
              errors.push(`Unknown operation type: ${(operation as any).type}`);
          }
        } catch (error) {
          errors.push(
            `Error preparing operation ${operation.type} for key ${operation.key}: ${(error as Error).message}`
          );
        }
      }

      // 执行管道
      const pipelineResults = await pipeline.exec();

      // 处理结果
      for (let i = 0; i < pipelineResults.length; i++) {
        const [error, result] = pipelineResults[i];
        const operation = this.operations[i];

        if (error) {
          errors.push(
            `Error executing ${operation?.type} for key ${operation?.key}: ${error.message}`
          );
          results.push(null);
        } else {
          // 对于get操作，尝试解析JSON
          if (operation?.type === 'get' && result) {
            try {
              results.push(JSON.parse(result as string));
            } catch {
              results.push(result);
            }
          } else {
            results.push(result);
          }
        }
      }

      const executionTime = this.now() - startTime;

      this.logMetric('batch.execute', executionTime, errors.length === 0, {
        operationCount: this.operations.length,
        errorCount: errors.length,
      });

      return {
        success: errors.length === 0,
        results,
        errors,
        executionTime,
      };
    } catch (error) {
      const executionTime = this.now() - startTime;
      const errorMessage = `Batch execution failed: ${(error as Error).message}`;

      this.logMetric('batch.execute', executionTime, false, {
        operationCount: this.operations.length,
        error: errorMessage,
      });

      return {
        success: false,
        results: [],
        errors: [errorMessage],
        executionTime,
      };
    } finally {
      // 清空操作队列
      this.clear();
    }
  }

  /**
   * 清空操作队列
   */
  clear(): void {
    this.operations = [];
  }

  /**
   * 获取当前操作数量
   */
  getOperationCount(): number {
    return this.operations.length;
  }

  /**
   * 获取操作列表
   */
  getOperations(): BatchOperation[] {
    return [...this.operations];
  }

  /**
   * 设置最大批量大小
   */
  setMaxBatchSize(size: number): void {
    if (size <= 0) {
      throw new Error('Max batch size must be greater than 0');
    }
    this.maxBatchSize = size;
  }

  /**
   * 获取最大批量大小
   */
  getMaxBatchSize(): number {
    return this.maxBatchSize;
  }
}
